package com.hkzhao.reportingsystem.service.impl;

import cn.hutool.extra.template.engine.velocity.VelocityEngine;
import com.github.pagehelper.PageHelper;
import com.hkzhao.reportingsystem.Docutment.AddtionDiagnosis;
import com.hkzhao.reportingsystem.Docutment.TotalData;
import com.hkzhao.reportingsystem.common.api.CommonResult;
import com.hkzhao.reportingsystem.common.utils.JwtTokenUtil;
import com.hkzhao.reportingsystem.common.utils.RexUtil;
import com.hkzhao.reportingsystem.common.utils.TokenTranslate;
import com.hkzhao.reportingsystem.common.utils.TranslateToToken;
import com.hkzhao.reportingsystem.component.OverTimeCancelSender;
import com.hkzhao.reportingsystem.component.RegisterSender;
import com.hkzhao.reportingsystem.dao.AddtionDiagnosisRepository;
import com.hkzhao.reportingsystem.dao.ReportSystemDao;
import com.hkzhao.reportingsystem.dao.TotalDataRepository;
import com.hkzhao.reportingsystem.dto.CaseDto;
import com.hkzhao.reportingsystem.mbg.mapper.*;
import com.hkzhao.reportingsystem.mbg.model.*;
import com.hkzhao.reportingsystem.service.DoctorService;
import com.hkzhao.reportingsystem.service.RedisStringService;
import com.hkzhao.reportingsystem.service.RedisTmpService;
import org.omg.CosNaming.NamingContextExtPackage.StringNameHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.connection.ReactiveZSetCommands;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.swing.*;
import java.util.*;

@Service
public class DoctorServiceImpl implements DoctorService {
    private static final Logger LOGGER = LoggerFactory.getLogger(DoctorServiceImpl.class);
    @Value("${redis.key.expire.authCode}")
    private Long second;
    @Value("${redis.key.prefix.authCode}")
    private String auth_header;
    @Value("${redis.key.doctorRegister.authCode}")
    private String doctor_prefix;
    @Value("${redis.key.casePrefix.authCode}")
    private String redis_auth_Case_key;
    @Autowired
    private RedisStringService redisService;
    @Autowired
    private JavaMailSender mailSender;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired(required = false)
    private VelocityEngine velocityEngine;
    @Autowired(required = false)
    private DoctorMapper doctorMapper;
    @Autowired(required = false)
    private UserPermissionMapper userPermissionMapper;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private OverTimeCancelSender overTimeCancelSender;
    @Autowired
    private RegisterSender registerSender;
    @Autowired(required = false)
    private CaseMapper caseMapper;
    @Autowired(required = false)
    private ReportSystemDao reportSystemDao;
    @Autowired(required = false)
    private RedisTmpService redisTmpService;
    @Autowired
    private TokenTranslate tokenTranslate;
    @Autowired(required = false)
    private ProvinceMapper provinceMapper;
    @Autowired(required = false)
    private CityMapper cityMapper;
    @Autowired
    private AddtionDiagnosisRepository addtionDiagnosisRepository;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private TotalDataRepository totalDataRepository;
    @Override
    public CommonResult register(String username, String password, String worker_id, String doctor_type, String province,String identify_id,String validCode,String email) {
        if(getValidCode(email)==null)
            return CommonResult.failed("没有该邮箱的验证码");
        if(!getValidCode(email).equals(validCode))
            return CommonResult.failed("邮箱验证码错误");
        String  Doctor_token_id = TranslateToToken.GetGUID();
        if(redisService.get(doctor_prefix+username)!=null)
            return CommonResult.failed("该用户名也被占用,请重新输入");
        if(doctorMapper.selectByPrimaryKey(username)!=null)
            return CommonResult.failed("该用户名也被占用,请重新输入");
        Doctor doctor = new Doctor();
        doctor.setUsername(username);doctor.setWokerId(worker_id);
        doctor.setProvince(province);doctor.setIdentifyId(identify_id);
        doctor.setDoctorType(doctor_type);doctor.setDoctorTokenId(Doctor_token_id);doctor.setPassword(passwordEncoder.encode(password));
        doctor.setStatus(0);
        doctorMapper.insert(doctor);
        LOGGER.info("doctor register request username:{}",username);
        senDelayMessageCancelVerify(username);
        return CommonResult.success("成功注册用户，已提交申请,请等待12h审核");
    }

    public CommonResult sendDelayReigsterEmail(String username)
    {   String validCode = valid_register(username);
        long delayTimes = 3000;
        registerSender.sendMessage(new String[]{username,validCode},delayTimes);
        return CommonResult.success(validCode,"用户验证码");
    }
    private void senDelayMessageCancelVerify(String username)
    {
        long delayTimes = 60 * 60 * 1000 * 12;
        overTimeCancelSender.sendMessage(username, delayTimes);

    }
    private String valid_register(String emailaddress) {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 6; i++) {
            sb.append(random.nextInt(10));
        }
        redisService.set(auth_header+emailaddress,sb.toString());
        redisService.expire(auth_header+emailaddress,240);
        return sb.toString();
    }
    @Override
    public CommonResult send_email(String emailaddress, String message){
        /*SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("1223602915@qq.com");
        message.setTo(emailaddress);
        message.setSubject("主题：直报系统注册验证码");
        message.setText(sb);
        mailSender.send(message);*/
        return CommonResult.success(message,"成功发送该邮件");
    }
    private String getValidCode(String email){
      return   redisService.get(auth_header+email);
    }

    @Override
    public Doctor getDoctorByUsername(String username) {
        DoctorExample doctorExample = new DoctorExample();
        doctorExample.createCriteria().andUsernameEqualTo(username);
        List<Doctor> list = doctorMapper.selectByExample(doctorExample);
        if(list!=null&&list.size()>0)
            return list.get(0);
        return null;
    }



    @Override
    public String login(String username, String password) {
        String token = null;
        try{
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if(!passwordEncoder.matches(password,userDetails.getPassword()))
            {
                throw new BadCredentialsException("密码不正确");
            }
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            token = jwtTokenUtil.generateToken(userDetails);
        }catch (AuthenticationException e){
            LOGGER.warn("登录异常:{}",e.getMessage());
        }
        return token;
    }

    @Override
    public CommonResult cancelRegister(String username) {
        if(doctorMapper.selectByPrimaryKey(username)!=null){
        if(doctorMapper.selectByPrimaryKey(username).getStatus()!=0)
            return CommonResult.success("该注册已经被审核通过不需要延迟删除");
        send_email(username,"超时未审核请重新注册");
        doctorMapper.deleteByPrimaryKey(username);
        return CommonResult.success("成功删除");}
        else
        {
            return CommonResult.success("已经删除数据");
        }
    }

    @Override
    public CommonResult registerSendMail(String[] username_validCode) {
        send_email(username_validCode[0],"用户: "+username_validCode[0]+"的验证码为: "+username_validCode[1]);
        return CommonResult.success(username_validCode[0],"成功向该用户"+username_validCode[0]+"发送邮件");
    }

    @Override
    public CommonResult addCase(String Locate, String Note, String Telephone, int Age, String Level, String Disease_type, String gender,String name, HttpServletRequest request) {
        String username = tokenTranslate.GetUsernameByHeader(request);
        String token = doctorMapper.selectByPrimaryKey(username).getDoctorTokenId();
        if(username.length()==0)
            return CommonResult.failed("用户名不能为空");
        String uuid = TranslateToToken.GetGUID();
        Case c = new Case();c.setLocate(Locate);c.setCreateTime(new Date());c.setNote(Note);
        c.setTelephone(Telephone);c.setAge(Age);c.setDegree(Level);c.setDiseasetype(Disease_type);
        c.setCaseid(uuid);c.setGender(gender);c.setDoctortokenid(token);c.setInfectname(name);
        caseMapper.insert(c);
        //插入数据到mysql 剩下一个统计新增
        addCaseDataTOShow(Locate, Level);
        return CommonResult.success(uuid,"病例成功插入");
    }

    @Override
    public List<Case> getCaseByusername(HttpServletRequest request,int pageNum,int pageSize) {
        String username = tokenTranslate.GetUsernameByHeader(request);
        if(username.length()==0)
            return new ArrayList<>();
        Doctor doctor = doctorMapper.selectByPrimaryKey(username);
        CaseExample caseExample = new CaseExample();
        caseExample.createCriteria().andDoctortokenidEqualTo(doctor.getDoctorTokenId());
        PageHelper.startPage(pageNum,pageSize);
        return caseMapper.selectByExample(caseExample);
    }

    @Override
    public CommonResult addAuthCase(CaseDto caseDto) {

        redisTmpService.sAdd(redis_auth_Case_key,(Object) caseDto);
        return CommonResult.success(caseDto.getCaseId(),"成功插入审核redis数据库中");
    }
    public void addCaseDataTOShow(String Locate,  String Level)
    {   int i = Level.equals("治愈")?0:(Level.equals("死亡")?1:2);//0 治愈 1 死亡 2确诊
        List<Map<String,String>>  address = RexUtil.addressResolution(Locate);
        if(address!=null&&address.size()>0){
            //直辖市当省了  懒得搞这这么多分支if
            String[] province_city = address.get(0).get("province").length()==0?new String[]{address.get(0).get("city"),address.get(0).get("county")}
                                    :new String[]{address.get(0).get("province"),address.get(0).get("city")};
            Province p = provinceMapper.selectByPrimaryKey(province_city[0]);
            City c = cityMapper.selectByPrimaryKey(province_city[1]);
            c.setTotalDiagnosis(c.getTotalDiagnosis()+1);
            p.setTotalDiagnosis(p.getTotalDiagnosis()+1);
            mongoUpdate(); //每天更新新增
            if(i==0) //治愈
            {
                p.setTotalRecover(p.getTotalRecover()+1);
                c.setTotalRecover(c.getTotalRecover()+1);
            }
            else if(i==1)//死亡
            {
                p.setTotalDeath(p.getTotalDeath()+1);
                c.setTotalDeath(c.getTotalDeath()+1);
            }
            else  //确诊
            {
                p.setCurrentDiagnosis(p.getCurrentDiagnosis()+1);
                c.setCurrentDiagnosis(c.getCurrentDiagnosis()+1);
            }

            cityMapper.updateByPrimaryKey(c);
            provinceMapper.updateByPrimaryKey(p);
        }
    }
        private void mongoUpdate(){
            String date = TranslateToToken.formatSync8(new Date(),"yyyy-MM-dd");
            List<AddtionDiagnosis> addtionDiagnosisList = addtionDiagnosisRepository.findAllByDateEquals(date);
            if(addtionDiagnosisList!=null&&addtionDiagnosisList.size()>0)
            {
                Query query = new Query(Criteria.where("date").is(date));
                Update update = new Update();
                update.set("addtion_diagnosis",addtionDiagnosisList.get(0).getAddtion_diagnosis()+1);
                mongoTemplate.updateFirst(query,update,AddtionDiagnosis.class);
            }
            else
            {
                AddtionDiagnosis addtionDiagnosis = new AddtionDiagnosis();
                addtionDiagnosis.setId(null);
                addtionDiagnosis.setDate(date);
                addtionDiagnosis.setAddtion_diagnosis(1);
                addtionDiagnosisRepository.insert(addtionDiagnosis);
            }
        }

    @Override
    public void addRecordInMongo() {
        String date = TranslateToToken.formatSync8(new Date(),"yyyy-MM-dd");
        AddtionDiagnosis addtionDiagnosis = new AddtionDiagnosis();
        addtionDiagnosis.setAddtion_diagnosis(0);
        addtionDiagnosis.setDate(date);
        addtionDiagnosis.setId(null);
        addtionDiagnosisRepository.insert(addtionDiagnosis);
        LOGGER.info("凌晨更新新增数据项成功！");
    }

    @Override
    public void addDiagnosisInMongo() {
        String date = TranslateToToken.formatSync8(new Date(),"yyyy-MM-dd");
        TotalData totalData = new TotalData();
        int wuzhengzhuang  = reportSystemDao.getTotalMember("无症状");
        int qingzheng = reportSystemDao.getTotalMember("轻症");
        int zhongzheng  = reportSystemDao.getTotalMember("重症");
        int zhiyu  = reportSystemDao.getTotalMember("治愈");
        int siwang = reportSystemDao.getTotalMember("死亡");
        totalData.setId(null);
        totalData.setDate(date);totalData.setCurrent_diagnosis(qingzheng+zhongzheng+wuzhengzhuang);
        totalData.setTotal_death(siwang);totalData.setTotal_recover(zhiyu);
        totalData.setTotal_diagnosis(wuzhengzhuang+qingzheng+zhongzheng+zhiyu+siwang);
        LOGGER.info("统计昨日数据成功");
        totalDataRepository.insert(totalData);
    }
}
